#include "stdafx.h"
#include "h2image.h"
#include "h2log.h"

#pragma comment(lib, "gdiplus.lib")

map_vector<Gdiplus::Bitmap*>    H2IMG::_bitmaps;
ULONG_PTR                       H2IMG::_gdiplus_token = 0;
h2painter                       H2IMG::_draw_inst;
h2painter*                      H2IMG::_painter = &_draw_inst;

bool H2IMG::init()
{
    release();
    Gdiplus::GdiplusStartupInput gdiplusStartupInput;
    Gdiplus::GdiplusStartup(&_gdiplus_token, &gdiplusStartupInput, NULL);
    return true;
}


void H2IMG::release()
{ 
    for(int i = 0; i < _bitmaps.length(); ++i)
    {
        delete _bitmaps[i];
    }
    _bitmaps.release(); 

    if(_gdiplus_token)
    {
        Gdiplus::GdiplusShutdown(_gdiplus_token);
        _gdiplus_token = 0;
    }
}


bool H2IMG::load(const wchar_t* file, const wchar_t* name, int count)
{
    Gdiplus::Bitmap *pBmp = new Gdiplus::Bitmap(file);

    if(!pBmp || pBmp->GetLastStatus() != Gdiplus::Ok)
    {
        if(pBmp) delete pBmp;
        return false;
    }

    if(count <= 1)
    {
        _bitmaps[_bitmaps.create(name)] = pBmp;
        return true;
    }

    int width = pBmp->GetWidth() / count;

    for(UINT x = 0; x < pBmp->GetWidth(); x += width)
    {
        _bitmaps[_bitmaps.create(x == 0 ? name : L"")] = pBmp->Clone(Gdiplus::REAL(x), Gdiplus::REAL(0), Gdiplus::REAL(width), Gdiplus::REAL(pBmp->GetHeight()), PixelFormatDontCare);
    }

    delete pBmp;

    return true;
}


void h2painter::draw_edge(Gdiplus::Graphics &g, RECT& rect, int tra)
{
    Gdiplus::Pen pen(Gdiplus::Color(tra, 128, 128, 128));
    g.DrawRectangle(&pen, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
}



void h2painter::draw_image(Gdiplus::Graphics &g, Gdiplus::Bitmap* bmp, RECT& rect, int tra)
{
    Gdiplus::ColorMatrix colorMatrix = {
        1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
        0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
        0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
        0.0f, 0.0f, 0.0f, ((float)tra)/100, 0.0f,
        0.0f, 0.0f, 0.0f, 0.0f, 1.0f };


    Gdiplus::ImageAttributes imageAtt;
    imageAtt.SetColorMatrix(&colorMatrix, Gdiplus::ColorMatrixFlagsDefault, Gdiplus::ColorAdjustTypeBitmap);

    g.DrawImage(bmp, Gdiplus::Rect(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top),
        0, 0, bmp->GetWidth(), bmp->GetHeight(), Gdiplus::UnitPixel, &imageAtt);
}


void h2painter::draw_text(Gdiplus::Graphics &g, RECT& rect, const wchar_t* txt, int tra)
{
    Gdiplus::FontFamily   fontFamily(*_font_family);
    Gdiplus::Font         font(&fontFamily, Gdiplus::REAL(_font_size), Gdiplus::FontStyleRegular , Gdiplus::UnitPixel);
    Gdiplus::RectF        rectF(Gdiplus::REAL(rect.left), Gdiplus::REAL(rect.top), Gdiplus::REAL(rect.right-rect.left), Gdiplus::REAL(rect.bottom-rect.top));
    Gdiplus::SolidBrush   solidBrush(Gdiplus::Color(255 * tra / 100, GetRValue(_text_color), GetGValue(_text_color), GetBValue(_text_color)));
    g.SetTextRenderingHint(Gdiplus::TextRenderingHintAntiAlias);
    Gdiplus::StringFormat stringFormat;
    stringFormat.SetAlignment(_text_align < 0 ? Gdiplus::StringAlignmentNear : ( _text_align > 0 ? Gdiplus::StringAlignmentFar : Gdiplus::StringAlignmentCenter));
    stringFormat.SetLineAlignment(_line_align < 0 ? Gdiplus::StringAlignmentNear : ( _line_align > 0 ? Gdiplus::StringAlignmentFar : Gdiplus::StringAlignmentCenter));
    g.DrawString(txt, -1, &font, rectF, &stringFormat, &solidBrush);
}

void h2painter::measure_text(const wchar_t* txt, int len, int* width, int* height)
{
    Gdiplus::Graphics gra((HWND)NULL);
    Gdiplus::FontFamily   fontFamily(*_font_family);
    Gdiplus::Font         font(&fontFamily, Gdiplus::REAL(_font_size), Gdiplus::FontStyleRegular , Gdiplus::UnitPixel);
    Gdiplus::StringFormat stringFormat;
    stringFormat.SetAlignment(_text_align < 0 ? Gdiplus::StringAlignmentNear : ( _text_align > 0 ? Gdiplus::StringAlignmentFar : Gdiplus::StringAlignmentCenter));
    stringFormat.SetLineAlignment(_line_align < 0 ? Gdiplus::StringAlignmentNear : ( _line_align > 0 ? Gdiplus::StringAlignmentFar : Gdiplus::StringAlignmentCenter));
    Gdiplus::SizeF layout(0,0), size(0,0);
    gra.SetTextRenderingHint(Gdiplus::TextRenderingHintAntiAlias);
    gra.MeasureString(txt, len, &font, layout, &stringFormat, &size);
    if(width) *width = (int)ceil(size.Width);
    if(height) *height = (int)ceil(size.Height);
}

void h2painter::draw_background(Gdiplus::Graphics &g, RECT& rect, int tra)
{
    Gdiplus::Rect rc(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
    Gdiplus::Color c1, c2;

    c1 = Gdiplus::Color(255 * tra / 100, 192, 192, 255);
    c2 = Gdiplus::Color(255 * tra / 100, 224, 224, 255);

    Gdiplus::LinearGradientBrush brush(rc, c1, c2, Gdiplus::LinearGradientModeVertical);
    g.FillRectangle(&brush, rc);
}

void h2painter::draw_mask(Gdiplus::Graphics &g, RECT& rect, int tra)
{
    Gdiplus::Rect rc(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
    Gdiplus::Color c1, c2;

    c1 = Gdiplus::Color(255 * tra / 100, 255, 255, 192);
    c2 = Gdiplus::Color(255 * tra / 100, 255, 255, 224);

    Gdiplus::LinearGradientBrush brush(rc, c1, c2, Gdiplus::LinearGradientModeVertical);
    g.FillRectangle(&brush, rc);
}

void h2painter::draw_highlight(Gdiplus::Graphics &g, RECT& rect, int tra)
{
    Gdiplus::Rect rc(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
    Gdiplus::Color c1, c2;

    c1 = Gdiplus::Color(255 * tra / 100, 255, 255, 224);
    c2 = Gdiplus::Color(255 * tra / 100, 255, 255, 128);

    Gdiplus::LinearGradientBrush brush(rc, c1, c2, Gdiplus::LinearGradientModeVertical);
    g.FillRectangle(&brush, rc);
}


void h2painter::draw_selected(Gdiplus::Graphics &g, RECT& rect, int tra)
{
    Gdiplus::Rect rc(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
    Gdiplus::Color c1, c2;

    c1 = Gdiplus::Color(255 * tra / 100, 255, 255, 96);
    c2 = Gdiplus::Color(255 * tra / 100, 255, 255, 192);

    Gdiplus::LinearGradientBrush brush(rc, c1, c2, Gdiplus::LinearGradientModeVertical);
    g.FillRectangle(&brush, rc);
}
